import win32gui
import win32process
import win32api
import pyaudio
import numpy as np
import threading
import time
from collections import deque

class ProcessAudioCapture:
    def __init__(self,volume_threshold=0.3):
        self.target_window_title = None
        self.target_process_id = None
        self.is_monitoring = False
        self.volume_threshold = volume_threshold
        self.callback_func = None
        self.audio_buffer = deque(maxlen=1000)
        
        # PyAudio设置
        self.sample_rate = 44100
        self.chunk_size = 1024
        self.audio = pyaudio.PyAudio()
        
        
    def find_window_by_title(self, title_pattern):
        """根据窗口标题查找窗口"""
        def enum_windows_callback(hwnd, windows):
            if win32gui.IsWindowVisible(hwnd):
                window_title = win32gui.GetWindowText(hwnd)
                if title_pattern.lower() in window_title.lower():
                    windows.append((hwnd, window_title))
            return True
        
        windows = []
        win32gui.EnumWindows(enum_windows_callback, windows)
        return windows
    
    def get_process_id_from_window(self, hwnd):
        """从窗口句柄获取进程ID"""
        try:
            _, process_id = win32process.GetWindowThreadProcessId(hwnd)
            return process_id
        except Exception as e:
            print(f"获取进程ID失败: {e}")
            return None
    
    def setup_audio_capture(self):
        """设置音频捕获"""
        # 获取所有音频设备
        device_count = self.audio.get_device_count()
        test_devices = []
        for device_index in range(device_count):
            info = self.audio.get_device_info_by_index(device_index)
            if info['maxInputChannels'] > 0:
                test_devices.append((device_index, info))
        for device_index, info in test_devices:
            print(f"找到音频设备: {info['name']} (ID: {device_index})")
            try:
                # 使用WASAPI循环模式捕获音频
                # 捕获设备0的音频输出
                # device_index = 0  # 默认设备
                device_info = self.audio.get_device_info_by_index(device_index)
                print(f"使用设备: {device_info['name']} (ID: {device_index})")

                self.stream = self.audio.open(
                    format=pyaudio.paFloat32,
                    channels=2,  # 立体声
                    rate=self.sample_rate,
                    input=True,
                    input_device_index=device_index,
                    frames_per_buffer=self.chunk_size,
                    stream_callback=self._audio_callback
                )
                return True
            except Exception as e:
                print(f"设置音频捕获失败: {e}")
                return False
    
    def _audio_callback(self, in_data, frame_count, time_info, status):
        """音频回调函数"""
        if self.is_monitoring:
            # 转换为numpy数组
            audio_data = np.frombuffer(in_data, dtype=np.float32)
            
            # 计算音量
            volume = np.sqrt(np.mean(audio_data**2))
            self.audio_buffer.append(volume)
            
            # 检查阈值
            if volume >= self.volume_threshold:
                if self.callback_func:
                    self.callback_func(volume)
        
        return (in_data, pyaudio.paContinue)
    
    def start_monitoring(self, window_title, callback=None):
        """开始监听指定窗口的应用"""
        self.target_window_title = window_title
        self.callback_func = callback
        
        # # 查找目标窗口
        # windows = self.find_window_by_title(window_title)
        # if not windows:
        #     print(f"未找到包含 '{window_title}' 的窗口")
        #     return False
        
        # hwnd, title = windows[0]
        # self.target_process_id = self.get_process_id_from_window(hwnd)
        
        # print(f"找到目标窗口: {title} (PID: {self.target_process_id})")
        
        # 设置音频捕获
        if not self.setup_audio_capture():
            return False
        
        self.is_monitoring = True
        self.stream.start_stream()
        
        # print(f"开始监听 {title} 的音频...")
        return True
    
    def stop_monitoring(self):
        """停止监听"""
        self.is_monitoring = False
        if hasattr(self, 'stream'):
            self.stream.stop_stream()
            self.stream.close()
        print("音频监听已停止")
    
    def get_current_volume(self):
        """获取当前音量"""
        if self.audio_buffer:
            return self.audio_buffer[-1]
        return 0.0
    
    def get_volume_peak(self, samples=10):
        """获取音量峰值"""
        if len(self.audio_buffer) >= samples:
            return max(list(self.audio_buffer)[-samples:])
        elif self.audio_buffer:
            return max(self.audio_buffer)
        return 0.0
    

if __name__ == "__main__":
    def volume_callback(volume):
        print(f"检测到音量: {volume:.4f}")
    
    audio_capture = ProcessAudioCapture()
    
    # 替换为你要监听的窗口标题
    target_window_title = "魔兽世界"
    
    if audio_capture.start_monitoring(target_window_title, callback=volume_callback):
        try:
            while True:
                current_volume = audio_capture.get_current_volume()
                volume_peak = audio_capture.get_volume_peak()
                print(f"当前音量: {current_volume:.4f}, 峰值音量: {volume_peak:.4f}")
                time.sleep(.2)
        except KeyboardInterrupt:
            audio_capture.stop_monitoring()
    else:
        print("无法开始音频监听")